#region Usings

using log4net;
using Ninject.Core;
using Karma.Framework.Core.Services.Invoker.Cache;
using Karma.Framework.Core.Utils;

#endregion

namespace Karma.Framework.Core.Services.Invoker
{
    [Singleton]
    public class ServiceInvoker : IServiceInvoker
    {
        private static bool _isInitialized;
        private static ILog LOG = LogManager.GetLogger(typeof (ServiceInvoker).Name);

        #region IServiceInvoker Members

        public object Invoke(string service, string method, params object[] parameters)
        {
            if (!_isInitialized)
            {
                Initialize();
            }

            var serviceFactoryMethod = InvokerCache.GetFactoryMethod(service);
            if (LOG.IsDebugEnabled)
            {
                LOG.Debug(string.Format("The IoC factory method: {0}.", serviceFactoryMethod));
            }
            // -> IoCFactory.Resolve<serviceType>();
            var serviceInstance = serviceFactoryMethod.Invoke(null, new object[] {});
            if (LOG.IsDebugEnabled)
            {
                LOG.Debug(string.Format("The service instance: {0}.", serviceInstance));
            }
            var methodToInvoke = InvokerCache.GetServiceMethod(service, method, parameters);
            if (LOG.IsDebugEnabled)
            {
                LOG.Debug(string.Format("The method to invoke: {0}.", methodToInvoke));
            }
            if (LOG.IsDebugEnabled)
            {
                LOG.Debug(string.Format("Parameters array: [{0}] [{1}].", parameters.Length, parameters.ItemsToString()));
            }
            // -> service.method(parameters)
            var result = methodToInvoke.Invoke(serviceInstance, parameters);
            if (LOG.IsDebugEnabled)
            {
                LOG.Debug(string.Format("The result of the invokation: {0}.", result));
            }
            return result;
        }

        public void Initialize()
        {
            if (LOG.IsDebugEnabled)
            {
                LOG.Debug("Initializing ServiceInvoker...");
            }
            InvokerCache.Initialize();
            _isInitialized = true;
            if (LOG.IsDebugEnabled)
            {
                LOG.Debug("Service invoker initialized.");
            }
        }

        #endregion
    }
}